#include "xlcomm/base/current_thread.h"

#include <sstream>

#include "xlcomm/define.h"

#ifdef _WIN32
#include <process.h>
#include <windows.h>
#elif __APPLE__
#include <pthread.h>
#else
#include <execinfo.h>
#include <sys/syscall.h>
#include <unistd.h>
#endif  // _WIN32

namespace xlcomm {

uint64_t CurrentThread::GetThreadId() {
#ifdef _WIN32
  DWORD tid = ::GetCurrentThreadId();
  return static_cast<uint64_t>(tid);
#elif __APPLE__
  uint64_t tid;
  pthread_threadid_np(nullptr, &tid);
  return tid;
#else
  return static_cast<uint64_t>(::syscall(SYS_gettid));
#endif  // _WIN32
}

std::string CurrentThread::StackTrace() {
#ifdef _WIN32
#else
  std::ostringstream oss;
  oss << "StackTrace:\n";
  const int kBufferSize = 64;
  void* buffer[kBufferSize];
  int num = backtrace(buffer, kBufferSize);

  char** strings = nullptr;
  strings = backtrace_symbols(buffer, num);
  if (strings == nullptr) {
    oss << "backtrace_symbols error";
  }
  for (int i = 0; i < num; ++i) {
    oss << strings[i] << "\n";
  }
  free(strings);
  return oss.str();
#endif  // _WIN32
}

}  // namespace xlcomm